#pragma once
#include "JuliaNervus.h"
#include "TrainingCaseDB.h"

class JuliaChainDefine
{
public:
	JuliaChainDefine( ):m_nExpire(0),m_pOutputNervusPos(NULL),m_nSize(0)
	{};

	~JuliaChainDefine(){delete []m_pOutputNervusPos;};

	void MakeStaticChain( int nSize )
	{
		m_nSize = nSize;
		m_nExpire = 10000;
		m_pOutputNervusPos = new int[nSize];
		for( int i=1; i<m_nSize; i++ )
			m_pOutputNervusPos[i] = i+1;
		m_pOutputNervusPos[0] = m_nSize-1;
		//m_pOutputNervusPos[m_nSize-1] = -1;
	};

	void MakeEmptyChain( int nSize, int nExpire )
	{
		m_nSize = nSize;
		m_nExpire = nExpire;
		m_pOutputNervusPos = new int[nSize];
		for( int i=0; i<m_nSize; i++ )
			m_pOutputNervusPos[i] = -1;
	};

#if 0
	void MakeRandomChain( int nSize, int nExpire )
	{
#if 0
		m_nSize = nSize;
		m_nExpire = nExpire;
		m_pOutputNervusPos = new int[nSize];
		for( int i=0; i<m_nSize; i++ )
			m_pOutputNervusPos[i] = -1;
		for( int i=0; i<m_nSize; i++ )
		{
			m_pOutputNervusPos[i] = ((float)rand())/RAND_MAX*m_nSize;
			for( int j=0; j<i; j++ )
				if( m_pOutputNervusPos[i] == m_pOutputNervusPos[j] )
				{
					i--;
					break;
				}

		}
#endif
		//for( int i=0; i<m_nSize; i++ )
		//	printf("%d,",m_pOutputNervusPos[i]);
		//printf("\n");
		int ntmp[] = {26,12,25,29,6,10,24,8,17,15,20,11,16,30,22,4,19,0,7,5,3,31,9,28,2,21,14,27,1,23,18,13};
		m_nSize = nSize;
		m_nExpire = nExpire;
		m_pOutputNervusPos = new int[nSize];
		memcpy( m_pOutputNervusPos, ntmp, sizeof(ntmp) );
	};
#endif

	void Print( void )
	{
		printf( "[%d,life %d]", m_nSize, m_nExpire );
		for( int i=0; i<m_nSize; i++ )
			printf(",%d",m_pOutputNervusPos[i]);
		printf("\n");
	}

	int Save( int* buf )
	{
		int nLen=0;
		buf[nLen++] = m_nSize;
		buf[nLen++] = m_nExpire;
		for( int i=0; i<m_nSize; i++ )
			buf[nLen++] = m_pOutputNervusPos[i];
		return nLen;
	};

	int Load( int* buf )
	{
		int nIdx=0;

		m_nSize = buf[nIdx++];
		m_nExpire = buf[nIdx++];

		delete []m_pOutputNervusPos;
		m_pOutputNervusPos = new int[m_nSize];

		for( int i=0; i<m_nSize; i++ )
			m_pOutputNervusPos[i] = buf[nIdx++];
		return nIdx;
	};

	void Set( int nNervusNum, int nToNervusNum )
	{
		int nSave = m_pOutputNervusPos[nNervusNum];
		m_pOutputNervusPos[nNervusNum] = nToNervusNum;

		for( int i=0; i<m_nSize; i++ )
			if( i!=nNervusNum && nToNervusNum == m_pOutputNervusPos[i] )
			{
				m_pOutputNervusPos[i] = nSave;
				break;
			}
	};

	int m_nExpire;
	int *m_pOutputNervusPos;
	int m_nSize;
};

class JuliaNervusChain
{
public:
	JuliaNervusChain(int nNervusCount, int nNervusSignalCount, Complex);
	~JuliaNervusChain(void);

	void SetOtherChain( int nIdx, JuliaNervusChain* pChain )
	{
		m_pSideChain[nIdx]=pChain;
	};
	void SetChainParam( int nIdx, JuliaChainDefine& cDef );

	bool RunCase( CTrainingCase* pCase );
	bool ProcessSignal( Complex input );

	Complex GetResult( void ){return cOut;};
	JuliaNervus* GetNervusAt( int nIdx ){return &m_jNervusArray[nIdx];};
private:
	JuliaNervus *m_jNervusArray;
	int m_nNervusCount;
	JuliaNervus m_jEndNervus;
	JuliaNervus m_jEmptyNervus;
	Complex cTmp;
	Complex cOut;
	JuliaNervusChain* m_pSideChain[NERVUS_CHAIN_COUNT-1];
};

